{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Quick Example [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# A dictionary is a data structure that maps keys to values in the same way\n",
    "# that a list maps indexes to values. However, keys can be any immutable value!\n",
    "\n",
    "stateMap = { 'pittsburgh':'PA', 'chicago':'IL', 'seattle':'WA', 'boston':'MA' }\n",
    "city = input(\"Enter a city name --> \").lower()\n",
    "if (city in stateMap):\n",
    "    print(city.title(), \"is in\", stateMap[city])\n",
    "else:\n",
    "    print(\"Sorry, never heard of it.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another Example:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "counts = dict()\n",
    "while True:\n",
    "    n = int(input(\"Enter an integer (0 to end) --> \"))\n",
    "    if (n == 0): break\n",
    "    if (n in counts):\n",
    "        counts[n] += 1\n",
    "    else:\n",
    "        counts[n] = 1\n",
    "    print(\"I have seen\", n, \"a total of\", counts[n], \"time(s)\")\n",
    "print(\"Done, counts:\", counts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating Dictionaries [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create an empty dictionary\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = dict()\n",
    "print(d)    # prints {}\n",
    "\n",
    "# We can also use empty braces\n",
    "d = { }\n",
    "print(d)    # prints {}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a dictionary from a list of (key, value) pairs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pairs = [(\"cow\", 5), (\"dog\", 98), (\"cat\", 1)]\n",
    "d = dict(pairs)\n",
    "print(d)    # unpredictable order!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Statically-allocate a dictionary\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = { \"cow\":5, \"dog\":98, \"cat\":1 }\n",
    "print(d)    # ditto!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using Dictionaries [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# We can interact with dictionaries in a similar way to lists/sets\n",
    "d = { \"a\" : 1, \"b\" : 2, \"c\" : 3 }\n",
    "\n",
    "print(len(d)) # prints 3, the number of key-value pairs\n",
    "\n",
    "print(\"a\" in d) # prints True\n",
    "print(2 in d) # prints False - we check the keys, not the values\n",
    "print(2 not in d) # prints True\n",
    "print(\"a\" not in d) # prints False\n",
    "\n",
    "print(d[\"a\"]) # finds the value associated with the given key. Crashes if the key is not in d\n",
    "print(d.get(\"z\", 42)) # finds the value of the key if the key is in the dictionary,\n",
    "# or returns the second (default) value if the key is not in d\n",
    "\n",
    "d[\"e\"] = \"wow\" # adds a new key-value pair to the dictionary, or updates the value of a current key\n",
    "del d[\"e\"] # removes the key-value pair specified from the dictionary. Crashes if the key is not in d\n",
    "\n",
    "for key in d:\n",
    "    print(key, d[key]) # we can iterate over the keys, then print out the keys or corresponding values"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Properties of Dictionaries [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dictionaries Map Keys to Values [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ages = dict()\n",
    "key = \"fred\"\n",
    "value = 38\n",
    "ages[key] = value  # \"fred\" is the key, 38 is the value\n",
    "print(ages[key])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Keys are Sets [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Keys are unordered\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = dict()\n",
    "d[2] = 100\n",
    "d[4] = 200\n",
    "d[8] = 300\n",
    "print(d)  # unpredictable order"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Keys are unique\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = dict()\n",
    "d[2] = 100\n",
    "d[2] = 200\n",
    "d[2] = 400\n",
    "print(d)  # { 2:400 }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Keys must be immutable\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "d = dict()\n",
    "a = [1] # lists are mutable, so...\n",
    "d[a] = 42 # Error: unhashable type: 'list'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Values are Unrestricted [Pre-reading]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# values may be mutable\n",
    "d = dict()\n",
    "a = [1,2]\n",
    "d[\"fred\"] = a\n",
    "print(d[\"fred\"])\n",
    "a += [3]\n",
    "print(d[\"fred\"]) # sees change in a!\n",
    "\n",
    "# but keys may not be mutable\n",
    "d[a] = 42       # TypeError: unhashable type: 'list'"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dictionaries are Very Efficient\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As mentioned above, a dictionary's keys are stored as a set. This means that finding where a key is stored takes constant time. This lets us look up a dictionary's value based on a key in constant time too!\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Some Worked Examples Using Dictionaries\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## isAnagram(s1, s2)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we rewrite the 1d-list isAnagram example only using a dictionary instead.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "#: Option 1: initializing d[key] to 0:\n",
    "def letterCounts(s):\n",
    "    counts = dict()\n",
    "    for ch in s.upper():\n",
    "        if ch.isalpha():\n",
    "            if ch not in counts:\n",
    "                counts[ch] = 0\n",
    "            counts[ch] += 1\n",
    "    return counts\n",
    "\n",
    "# Option 2: using d.get(key, defaultValue):\n",
    "def letterCounts(s):\n",
    "    counts = dict()\n",
    "    for ch in s.upper():\n",
    "        if ch.isalpha():\n",
    "            counts[ch] = counts.get(ch, 0) + 1\n",
    "    return counts\n",
    "\n",
    "# Option 3: using defaultdict(lambda: defaultValue)\n",
    "#    Note that defaultdict is not part of the\n",
    "#    required 112 subset, but it is very handy.\n",
    "def letterCounts(s):\n",
    "    counts = defaultdict(lambda: 0)\n",
    "    for ch in s.upper():\n",
    "        if ch.isalpha():\n",
    "            counts[ch] += 1\n",
    "    return counts\n",
    "\n",
    "# Regardless, this makes isAnagram clear and efficient:\n",
    "def isAnagram(s1, s2):\n",
    "    return (letterCounts(s1) == letterCounts(s2))\n",
    "\n",
    "def testIsAnagram():\n",
    "    print(\"Testing isAnagram()...\", end=\"\")\n",
    "    assert(isAnagram(\"\", \"\") == True)\n",
    "    assert(isAnagram(\"abCdabCd\", \"abcdabcd\") == True)\n",
    "    assert(isAnagram(\"abcdaBcD\", \"AAbbcddc\") == True)\n",
    "    assert(isAnagram(\"abcdaabcd\", \"aabbcddcb\") == False)\n",
    "    print(\"Passed!\")\n",
    "\n",
    "testIsAnagram()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note: while collections is not part of the 112 required curriculum, it is an interesting and sometimes very helpful module. For more, see here.\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## mostFrequent(L)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mostFrequent(L):\n",
    "    # Return most frequent element in L, resolving ties arbitrarily.\n",
    "    maxValue = None\n",
    "    maxCount = 0\n",
    "    counts = dict()\n",
    "    for element in L:\n",
    "        count = 1 + counts.get(element, 0)\n",
    "        counts[element] = count\n",
    "        if (count > maxCount):\n",
    "            maxCount = count\n",
    "            maxValue = element\n",
    "    return maxValue\n",
    "\n",
    "def testMostFrequent():\n",
    "    print(\"Testing mostFrequent()... \", end=\"\")\n",
    "    assert(mostFrequent([2,5,3,4,6,4,2,4,5]) == 4)\n",
    "    assert(mostFrequent([2,3,4,3,5,3,6,3,7]) == 3)\n",
    "    assert(mostFrequent([42]) == 42)\n",
    "    assert(mostFrequent([]) == None)\n",
    "    print(\"Passed!\")\n",
    "\n",
    "testMostFrequent()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## mostPopularNames()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# mostPopularNames.py\n",
    "# example creating a dictionary\n",
    "# from real data on the web\n",
    "\n",
    "# This data is copied from:\n",
    "# https://www.ssa.gov/oact/babynames/decades/century.html\n",
    "\n",
    "mostPopularNamesData = '''\\\n",
    "1    James   4,735,694   Mary    3,265,105\n",
    "2   John    4,502,387   Patricia    1,560,897\n",
    "3   Robert  4,499,901   Jennifer    1,467,664\n",
    "4   Michael 4,330,025   Linda   1,448,309\n",
    "5   William 3,601,719   Elizabeth   1,428,981\n",
    "6   David   3,563,170   Barbara 1,402,428\n",
    "7   Richard 2,467,544   Susan   1,104,407\n",
    "8   Joseph  2,352,889   Jessica 1,045,519\n",
    "9   Thomas  2,160,330   Sarah   993,847\n",
    "10  Charles 2,106,078   Karen   985,728\n",
    "11  Christopher 2,032,843   Nancy   969,544\n",
    "12  Daniel  1,889,640   Lisa    965,003\n",
    "13  Matthew 1,600,285   Margaret    944,344\n",
    "14  Anthony 1,403,920   Betty   938,638\n",
    "15  Donald  1,348,220   Sandra  873,609\n",
    "16  Mark    1,346,509   Ashley  847,504\n",
    "17  Paul    1,286,846   Dorothy 847,468\n",
    "18  Steven  1,281,302   Kimberly    838,235\n",
    "19  Andrew  1,252,016   Emily   826,262\n",
    "20  Kenneth 1,226,558   Donna   823,285\n",
    "21  Joshua  1,214,872   Michelle    811,401\n",
    "22  Kevin   1,172,372   Carol   807,303\n",
    "23  Brian   1,166,797   Amanda  772,882\n",
    "24  George  1,159,331   Melissa 753,157\n",
    "25  Edward  1,097,742   Deborah 739,809\n",
    "26  Ronald  1,073,062   Stephanie   738,123\n",
    "27  Timothy 1,069,165   Rebecca 729,683\n",
    "28  Jason   1,035,285   Laura   721,299\n",
    "29  Jeffrey 975,104 Sharon  720,816\n",
    "30  Ryan    937,629 Cynthia 705,685\n",
    "31  Jacob   925,412 Kathleen    689,366\n",
    "32  Gary    899,858 Amy 680,682\n",
    "33  Nicholas    891,818 Shirley 668,154\n",
    "34  Eric    877,492 Angela  658,437\n",
    "35  Jonathan    844,121 Helen   652,923\n",
    "36  Stephen 840,005 Anna    629,400\n",
    "37  Larry   802,430 Brenda  606,286\n",
    "38  Justin  777,285 Pamela  592,694\n",
    "39  Scott   769,663 Nicole  588,265\n",
    "40  Brandon 759,155 Samantha    576,029\n",
    "41  Benjamin    730,425 Katherine   574,858\n",
    "42  Samuel  710,086 Emma    570,150\n",
    "43  Frank   707,244 Ruth    563,391\n",
    "44  Gregory 706,987 Christine   563,333\n",
    "45  Raymond 679,913 Catherine   550,466\n",
    "46  Alexander   666,982 Debra   548,279\n",
    "47  Patrick 663,725 Rachel  546,309\n",
    "48  Jack    637,347 Carolyn 542,250\n",
    "49  Dennis  611,319 Janet   541,277\n",
    "50  Jerry   602,696 Virginia    531,894\n",
    "51  Tyler   589,687 Maria   528,760\n",
    "52  Aaron   579,578 Heather 524,161\n",
    "53  Jose    559,823 Diane   515,256\n",
    "54  Henry   553,392 Julie   506,315\n",
    "55  Adam    551,342 Joyce   500,601\n",
    "56  Douglas 549,324 Victoria    481,786\n",
    "57  Nathan  544,555 Kelly   471,257\n",
    "58  Peter   540,603 Christina   471,012\n",
    "59  Zachary 537,934 Lauren  469,625\n",
    "60  Kyle    480,276 Joan    469,101\n",
    "61  Walter  476,581 Evelyn  466,314\n",
    "62  Harold  448,640 Olivia  464,246\n",
    "63  Jeremy  437,552 Judith  449,885\n",
    "64  Ethan   435,390 Megan   437,186\n",
    "65  Carl    431,805 Cheryl  436,878\n",
    "66  Keith   431,764 Martha  434,595\n",
    "67  Roger   429,723 Andrea  434,410\n",
    "68  Gerald  428,208 Frances 429,429\n",
    "69  Christian   425,034 Hannah  426,616\n",
    "70  Terry   422,106 Jacqueline  420,348\n",
    "71  Sean    418,691 Ann 412,411\n",
    "72  Arthur  415,722 Gloria  409,072\n",
    "73  Austin  411,665 Jean    407,127\n",
    "74  Noah    409,039 Kathryn 406,120\n",
    "75  Lawrence    407,197 Alice   404,664\n",
    "76  Jesse   388,484 Teresa  404,603\n",
    "77  Joe 388,230 Sara    401,653\n",
    "78  Bryan   381,581 Janice  400,210\n",
    "79  Billy   379,560 Doris   395,048\n",
    "80  Jordan  378,141 Madison 387,071\n",
    "81  Albert  377,227 Julia   383,225\n",
    "82  Dylan   377,049 Grace   379,239\n",
    "83  Bruce   375,986 Judy    378,014\n",
    "84  Willie  367,775 Abigail 373,862\n",
    "85  Gabriel 352,072 Marie   373,633\n",
    "86  Alan    348,591 Denise  371,019\n",
    "87  Juan    345,375 Beverly 370,608\n",
    "88  Logan   341,413 Amber   369,981\n",
    "89  Wayne   339,139 Theresa 369,848\n",
    "90  Ralph   338,689 Marilyn 369,847\n",
    "91  Roy 338,079 Danielle    367,791\n",
    "92  Eugene  330,306 Diana   358,617\n",
    "93  Randy   327,821 Brittany    358,579\n",
    "94  Vincent 322,824 Natalie 352,644\n",
    "95  Russell 321,274 Sophia  351,883\n",
    "96  Louis   320,157 Rose    351,296\n",
    "97  Philip  315,423 Isabella    342,345\n",
    "98  Bobby   313,302 Alexis  339,548\n",
    "99  Johnny  308,243 Kayla   339,169\n",
    "100 Bradley 306,339 Charlotte   338,315'''\n",
    "\n",
    "# remove the commas in the numbers:\n",
    "mostPopularNamesData = mostPopularNamesData.replace(',','')\n",
    "\n",
    "def mostPopularNames():\n",
    "    mostPopularNameCounts = dict()\n",
    "\n",
    "    for line in mostPopularNamesData.splitlines():\n",
    "        index,name1,count1,name2,count2 = line.split()\n",
    "        mostPopularNameCounts[name1] = int(count1)\n",
    "        mostPopularNameCounts[name2] = int(count2)\n",
    "\n",
    "    while True:\n",
    "        name = input('Enter a name (or leave blank to quit) --> ')\n",
    "        name = name.capitalize()\n",
    "        if (name == ''): break\n",
    "        if (name in mostPopularNameCounts):\n",
    "            print(f'  {name} has a count of {mostPopularNameCounts[name]}')\n",
    "        else:\n",
    "            print(f'  {name} is not in the list!')\n",
    "\n",
    "mostPopularNames()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## simpleTextAdventure()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# simple-text-adventure.py\n",
    "\n",
    "# This is designed to be very simple, and to showcase\n",
    "# dictionaries and sets.  In fact, it uses dictionaries\n",
    "# in some ways that would be better-designed using\n",
    "# OOP (object-oriented programming).  We'll revisit this\n",
    "# example and improve upon it when we learn OOP later\n",
    "# this semester.\n",
    "\n",
    "# To win the (rather silly) game:\n",
    "#   get orange\n",
    "#   go east\n",
    "#   feed statue\n",
    "\n",
    "def simpleTextAdventure():\n",
    "    gameState = getInitialGameState()\n",
    "    while not gameState['gameOver']:\n",
    "        currentRoom = getCurrentRoom(gameState)\n",
    "        print(f'I am in {currentRoom[\"description\"]}')\n",
    "        print(f'I am carrying {thingsToString(gameState[\"inventory\"])}')\n",
    "        print(f'I can see {thingsToString(currentRoom[\"contents\"])}')\n",
    "        verb, noun = getCommand()\n",
    "        if (verb == 'go'): doGo(gameState, noun)\n",
    "        elif (verb == 'quit'): print('Goodbye!'); break\n",
    "        elif (verb == 'get'): doGet(gameState, noun)\n",
    "        elif (verb in ['put', 'drop']): doPut(gameState, noun)\n",
    "        elif (verb == 'feed'): doFeed(gameState, noun)\n",
    "\n",
    "def thingsToString(things):\n",
    "    things = sorted(things)\n",
    "    if (len(things) == 0):\n",
    "        return 'nothing'\n",
    "    elif (len(things) == 1):\n",
    "        return thingToString(things[0])\n",
    "    else:\n",
    "        result = ''\n",
    "        for i in range(len(things)):\n",
    "            if (i > 0):\n",
    "                if (i == len(things)-1):\n",
    "                    if (len(things) == 2):\n",
    "                        result += ' and '\n",
    "                    else:\n",
    "                        result += ', and '\n",
    "                else:\n",
    "                    result += ', '\n",
    "            result += thingToString(things[i])\n",
    "        return result\n",
    "\n",
    "def thingToString(thing):\n",
    "    if (thing[-1] == 's'):\n",
    "        return thing\n",
    "    elif (thing[0] in 'aeiou'):\n",
    "        return 'an ' + thing\n",
    "    else:\n",
    "        return 'a ' + thing\n",
    "\n",
    "def doGet(gameState, noun):\n",
    "    currentRoom = getCurrentRoom(gameState)\n",
    "    inventory = gameState['inventory']\n",
    "    contents = currentRoom['contents']\n",
    "    if (noun in contents):\n",
    "        contents.remove(noun)\n",
    "        inventory.add(noun)\n",
    "    else:\n",
    "        print('I cannot see that here.')\n",
    "\n",
    "def doFeed(gameState, noun):\n",
    "    currentRoom = getCurrentRoom(gameState)\n",
    "    inventory = gameState['inventory']\n",
    "    contents = currentRoom['contents']\n",
    "    if (noun != 'statue'):\n",
    "        print('I can only feed statues!')\n",
    "    elif ('statue' not in contents):\n",
    "        print('I do not see the statue here!')\n",
    "    elif ('orange' not in inventory):\n",
    "        print('I need to have food to feed it (like an orange)')\n",
    "    else:\n",
    "        inventory.remove('orange')\n",
    "        print('I fed the statue, and it came alive, and said:')\n",
    "        print('YOU WIN!!!!!!!')\n",
    "        gameState['gameOver'] = True\n",
    "\n",
    "def doPut(gameState, noun):\n",
    "    currentRoom = getCurrentRoom(gameState)\n",
    "    inventory = gameState['inventory']\n",
    "    contents = currentRoom['contents']\n",
    "    if (noun in inventory):\n",
    "        inventory.remove(noun)\n",
    "        contents.add(noun)\n",
    "    else:\n",
    "        print('I am not carrying that.')\n",
    "\n",
    "def doGo(gameState, direction):\n",
    "    currentRoom = getCurrentRoom(gameState)\n",
    "    exits = currentRoom['exits']\n",
    "    if (direction in exits):\n",
    "        gameState['currentRoomName'] = exits[direction]\n",
    "    else:\n",
    "        print(f\"I can't go {direction} from here!\")\n",
    "\n",
    "def getCurrentRoom(gameState):\n",
    "    name = gameState['currentRoomName']\n",
    "    return gameState[name]\n",
    "\n",
    "def getCommand():\n",
    "    while True:\n",
    "        response = input('Your command --> ')\n",
    "        print()\n",
    "        if (response == 'help'):\n",
    "            print('No help yet!')\n",
    "        elif (response in ['quit', 'exit', 'bye']):\n",
    "            return 'quit','now'\n",
    "        else:\n",
    "            words = response.split()\n",
    "            if (len(words) != 2):\n",
    "                print('Please enter commands in the form VERB NOUN')\n",
    "                print('Or just enter \"help\" for more help.')\n",
    "            else:\n",
    "                return words\n",
    "\n",
    "def getInitialGameState():\n",
    "    return {\n",
    "        'gameOver': False,\n",
    "        'currentRoomName' : 'kitchen',\n",
    "        'inventory': { 'whistle' },\n",
    "        'kitchen':\n",
    "            {\n",
    "                'description':'a bright and airy kitchen',\n",
    "                'exits': { 'north':'study', 'east':'porch' },\n",
    "                'contents': { 'plates', 'cup', 'orange' },\n",
    "            },\n",
    "        'study':\n",
    "            {\n",
    "                'description':'a study full of piles and piles of books',\n",
    "                'exits': { 'south':'kitchen' },\n",
    "                'contents': { 'thesaurus', 'dictionary', },\n",
    "            },\n",
    "        'porch':\n",
    "            {\n",
    "                'description':'a huge covered porch with lots of chairs',\n",
    "                'exits': { 'west':'kitchen' },\n",
    "                'contents': { 'statue' },\n",
    "            },\n",
    "    }\n",
    "\n",
    "simpleTextAdventure()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "p2s",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.9.15"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
